package com.jjrwa.component;

import lombok.Getter;

import javax.swing.*;
import javax.swing.table.TableCellEditor;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;

@Getter
public class TableDataHandle<T extends ITableDataEntity> {

    private List<T> dataList;
    private Class<T> dataClassType;
    private Vector columnNames;
    private List<DataCache> dataCaches;
    private Set<Integer> notEditableCells;//不允许编辑的列

    public TableDataHandle(Class<T> dataClassType, List<T> dataList) {
        this.dataList = dataList;
        this.dataClassType = dataClassType;
        this.dataCaches = new ArrayList<>();
        this.columnNames = new Vector();
        this.notEditableCells = new HashSet<>();
        try {
            this.init();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("数据异常");
        }
    }

    private void init() throws IntrospectionException {

        BeanInfo beanInfo = Introspector.getBeanInfo(dataClassType);
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
        for (PropertyDescriptor p : propertyDescriptors) {
            Field field;
            try {
                field = dataClassType.getDeclaredField(p.getName());
                field.setAccessible(true);
            } catch (NoSuchFieldException e) {
                continue;
            }
            ITableField annotation = field.getAnnotation(ITableField.class);
            if (annotation == null) {
                continue;
            }
            if (annotation.notCellEditable()) {
                this.notEditableCells.add(annotation.sort());
            }
            this.dataCaches.add(new DataCache(p, annotation));
        }
        this.dataCaches.sort(Comparator.comparing(DataCache::getSort));

        //生成列
        //第一列为选择列
        columnNames.add("");
        for (DataCache dataCache : this.dataCaches) {
            columnNames.add(dataCache.columnName);
        }
        //最后一列为操作列
        columnNames.add("Handle");
    }

    /**
     * 设置列宽
     *
     * @param table
     */
    public void setPreferredWidth(JTable table) {
        int i = 0;
        table.getColumnModel().getColumn(i).setPreferredWidth(5);
        i++;
        for (DataCache dataCache : this.dataCaches) {
            table.getColumnModel().getColumn(i).setPreferredWidth(dataCache.preferredWidth);
            i++;
        }

        table.getColumnModel().getColumn(i).setPreferredWidth(20);
    }

    public Vector getRows() {
        Vector rows = new Vector();
        for (T t : this.dataList) {
            Vector row = new Vector();
            row.add(t.isSelected());
            for (DataCache dataCache : dataCaches) {
                try {
                    row.add(dataCache.readMethod.invoke(t));
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new RuntimeException("解析数据异常");
                }
            }
            row.add(" ");
            rows.add(row);
        }
        return rows;
    }

    public void updateValues(JTable table) {
        TableCellEditor cellEditor = table.getCellEditor();
        if (cellEditor != null) {
            boolean b = cellEditor.stopCellEditing();
            if (!b) {
                throw new RuntimeException("表格编辑错误");
            }
        }

        int rowIndex = 0;
        for (T t : this.dataList) {
            int columnIndex = 0;
            t.setSelected((Boolean) table.getValueAt(rowIndex, columnIndex));
            for (DataCache dataCache : this.dataCaches) {
                columnIndex++;
                try {
                    dataCache.writeMethod.invoke(t, table.getValueAt(rowIndex, columnIndex));
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new RuntimeException("数据处理异常");
                }
            }
            rowIndex++;
        }

    }

    private class DataCache {
        private String fieldName;
        private int sort;
        private String columnName;
        private int preferredWidth;
        private Method readMethod;
        private Method writeMethod;

        protected DataCache(PropertyDescriptor p, ITableField iTableField) {
            this.fieldName = p.getName();
            this.sort = iTableField.sort();
            this.columnName = iTableField.columnName();
            this.preferredWidth = iTableField.preferredWidth();
            this.readMethod = p.getReadMethod();
            this.writeMethod = p.getWriteMethod();
        }

        public int getSort() {
            return sort;
        }
    }
}
